From cb03fe8f31c0607b5488cb79f3339910600729fb Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 20 Oct 2021 20:30:08 +0200 Subject: [PATCH] gsk: Allow gsk_renderer_realize (renderer, NULL, NULL) That way, we can use renderers without surfaces. --- gsk/gl/gskglrenderer.c | 20 ++++++++++++++------ gsk/gskcairorenderer.c | 3 ++- gsk/gskrenderer.c | 27 ++++++++++++++++++--------- gsk/vulkan/gskvulkanrenderer.c | 11 +++++++++-- 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index 0b1e9eddda..b222e2b07a 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -90,12 +90,10 @@ gsk_gl_renderer_realize (GskRenderer *renderer, GskGLRenderer *self = (GskGLRenderer *)renderer; GdkGLContext *context = NULL; GskGLDriver *driver = NULL; + GdkDisplay *display; gboolean ret = FALSE; gboolean debug_shaders = FALSE; - g_assert (GSK_IS_GL_RENDERER (self)); - g_assert (GDK_IS_SURFACE (surface)); - if (self->context != NULL) return TRUE; @@ -103,8 +101,18 @@ gsk_gl_renderer_realize (GskRenderer *renderer, g_assert (self->context == NULL); g_assert (self->command_queue == NULL); - if (!(context = gdk_surface_create_gl_context (surface, error)) || - !gdk_gl_context_realize (context, error)) + if (surface == NULL) + { + display = gdk_display_get_default (); /* FIXME: allow different displays somehow ? */ + context = gdk_display_create_gl_context (display, error); + } + else + { + display = gdk_surface_get_display (surface); + context = gdk_surface_create_gl_context (surface, error); + } + + if (!context || !gdk_gl_context_realize (context, error)) goto failure; #ifdef G_ENABLE_DEBUG @@ -112,7 +120,7 @@ gsk_gl_renderer_realize (GskRenderer *renderer, debug_shaders = TRUE; #endif - if (!(driver = gsk_gl_driver_for_display (gdk_surface_get_display (surface), debug_shaders, error))) + if (!(driver = gsk_gl_driver_for_display (display, debug_shaders, error))) goto failure; self->command_queue = gsk_gl_driver_create_command_queue (driver, context); diff --git a/gsk/gskcairorenderer.c b/gsk/gskcairorenderer.c index 074b54b97f..3135acfdb1 100644 --- a/gsk/gskcairorenderer.c +++ b/gsk/gskcairorenderer.c @@ -59,7 +59,8 @@ gsk_cairo_renderer_realize (GskRenderer *renderer, { GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer); - self->cairo_context = gdk_surface_create_cairo_context (surface); + if (surface) + self->cairo_context = gdk_surface_create_cairo_context (surface); return TRUE; } diff --git a/gsk/gskrenderer.c b/gsk/gskrenderer.c index 7c35b051f9..ff4ff976ce 100644 --- a/gsk/gskrenderer.c +++ b/gsk/gskrenderer.c @@ -103,7 +103,7 @@ static GParamSpec *gsk_renderer_properties[N_PROPS]; static gboolean gsk_renderer_real_realize (GskRenderer *self, - GdkSurface *surface, + GdkSurface *surface, GError **error) { GSK_RENDERER_WARN_NOT_IMPLEMENTED_METHOD (self, realize); @@ -189,12 +189,12 @@ gsk_renderer_class_init (GskRendererClass *klass) /** * GskRenderer:realized: (attributes org.gtk.Property.get=gsk_renderer_is_realized) * - * Whether the renderer has been associated with a surface. + * Whether the renderer has been associated with a surface or draw context. */ gsk_renderer_properties[PROP_REALIZED] = g_param_spec_boolean ("realized", "Realized", - "The renderer has been associated with a surface", + "The renderer has been associated with a surface or draw context", FALSE, G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); @@ -281,11 +281,14 @@ gsk_renderer_is_realized (GskRenderer *renderer) /** * gsk_renderer_realize: * @renderer: a `GskRenderer` - * @surface: the `GdkSurface` renderer will be used on + * @surface: (nullable): the `GdkSurface` renderer will be used on * @error: return location for an error * * Creates the resources needed by the @renderer to render the scene * graph. + * + * Since GTK 4.6, the surface may be `NULL`, which allows using + * renderers without having to create a surface. */ gboolean gsk_renderer_realize (GskRenderer *renderer, @@ -296,10 +299,11 @@ gsk_renderer_realize (GskRenderer *renderer, g_return_val_if_fail (GSK_IS_RENDERER (renderer), FALSE); g_return_val_if_fail (!gsk_renderer_is_realized (renderer), FALSE); - g_return_val_if_fail (GDK_IS_SURFACE (surface), FALSE); + g_return_val_if_fail (surface == NULL || GDK_IS_SURFACE (surface), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - priv->surface = g_object_ref (surface); + if (surface) + priv->surface = g_object_ref (surface); if (!GSK_RENDERER_GET_CLASS (renderer)->realize (renderer, surface, error)) { @@ -399,13 +403,15 @@ gsk_renderer_render_texture (GskRenderer *renderer, /** * gsk_renderer_render: - * @renderer: a `GskRenderer` + * @renderer: a realized `GskRenderer` * @root: a `GskRenderNode` * @region: (nullable): the `cairo_region_t` that must be redrawn or %NULL * for the whole window * - * Renders the scene graph, described by a tree of `GskRenderNode` instances, - * ensuring that the given @region gets redrawn. + * Renders the scene graph, described by a tree of `GskRenderNode` instances + * to the renderer's surface, ensuring that the given @region gets redrawn. + * + * If the renderer has no associated surface, this function does nothing. * * Renderers must ensure that changes of the contents given by the @root * node as well as the area given by @region are redrawn. They are however @@ -428,6 +434,9 @@ gsk_renderer_render (GskRenderer *renderer, g_return_if_fail (GSK_IS_RENDER_NODE (root)); g_return_if_fail (priv->root_node == NULL); + if (priv->surface == NULL) + return; + if (region == NULL || priv->prev_node == NULL || GSK_RENDERER_DEBUG_CHECK (renderer, FULL_REDRAW)) { clip = cairo_region_create_rectangle (&(GdkRectangle) { diff --git a/gsk/vulkan/gskvulkanrenderer.c b/gsk/vulkan/gskvulkanrenderer.c index c91b14a384..86f7984805 100644 --- a/gsk/vulkan/gskvulkanrenderer.c +++ b/gsk/vulkan/gskvulkanrenderer.c @@ -114,12 +114,19 @@ gsk_vulkan_renderer_update_images_cb (GdkVulkanContext *context, static gboolean gsk_vulkan_renderer_realize (GskRenderer *renderer, - GdkSurface *window, + GdkSurface *surface, GError **error) { GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer); - self->vulkan = gdk_surface_create_vulkan_context (window, error); + if (surface == NULL) + { + g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED, + "The Vulkan renderer does not support surfaceless rendering yet."); + return FALSE; + } + + self->vulkan = gdk_surface_create_vulkan_context (surface, error); if (self->vulkan == NULL) return FALSE; -- 2.30.2